package org.muninn.niagara.services;

import javax.baja.sys.Action;
import javax.baja.sys.BComponent;
import javax.baja.sys.BIService;
import javax.baja.sys.BIcon;
import javax.baja.sys.BRelTime;
import javax.baja.sys.Clock;
import javax.baja.sys.Context;
import javax.baja.sys.Flags;
import javax.baja.sys.Property;
import javax.baja.sys.Slot;
import javax.baja.sys.Sys;
import javax.baja.sys.Type;
import javax.baja.sys.Clock.Ticket;
import javax.baja.util.BServiceContainer;

import com.tridium.platform.BSystemPlatformService;

public class BMuninnServiceContainer extends BComponent implements BIService
{
  public static final Property stationName = newProperty(3, "system", null);
  public void setStationName(String s) { setString(stationName, s); }
  public String getStationName() { return getString(stationName); }
  
  public static final Property hostID = newProperty(3, "", null);
  public void setHostID(String s) { setString(hostID, s); }
  public String getHostID() { return getString(hostID); }
  
  public static final Property muninnModuleVersion = newProperty(3, "", null);
  public void setMuninnModuleVersion(String s) { setString(muninnModuleVersion, s); }
  public String getMuninnModuleVersion() { return getString(muninnModuleVersion); }
  
  public static final Property licenseCode = newProperty(Flags.DEFAULT_ON_CLONE, "", null);
  public void setLicenseCode(String s) { setString(licenseCode, s); }
  public String getLicenseCode() { return getString(licenseCode); }
  
  public static final Property licensed = newProperty(Flags.READONLY, false);
  public void setLicensed(boolean b) { setBoolean(licensed, b); }
  public boolean getLicensed() { return getBoolean(licensed); }
  
  public static final Property enableSaveState = newProperty(0, false);
  public void setEnableSaveState(boolean b) { setBoolean(enableSaveState, b); }
  public boolean getEnableSaveState() { return getBoolean(enableSaveState); }
  
  public static final Property saveStateFrequency = newProperty(0, BRelTime.make(3600000));
  public void setSaveStateFrequency(BRelTime t) { set(saveStateFrequency, t); }
  public BRelTime getSaveStateFrequency() { return (BRelTime) get(saveStateFrequency); }
  
  public static final Property enableStationAutoSave = newProperty(0, false);
  public void setEnableStationAutoSave(boolean b) { setBoolean(enableStationAutoSave, b); }
  public boolean getEnableStationAutoSave() { return getBoolean(enableStationAutoSave); }
  
  public static final Property stationAutoSaveFrequency = newProperty(0, BRelTime.make(86400000));
  public void setStationAutoSaveFrequency(BRelTime t) { set(stationAutoSaveFrequency, t); }
  public BRelTime getStationAutoSaveFrequency() { return (BRelTime) get(stationAutoSaveFrequency); }
  
  public static final Property stationAutoSaveVersionsToKeep = newProperty(0, 1);
  public void setStationAutoSaveVersionsToKeep(int v) { setInt(stationAutoSaveVersionsToKeep, v); }
  public int getStationAutoSaveVersionsToKeep() { return getInt(stationAutoSaveVersionsToKeep); }
  
  public static final Action saveStation = newAction(0, null);
  public void saveStation() { invoke(saveStation, null); }
  public void doSaveStation() { Sys.getStation().save(); }
  
  public static final Action retryLicense = newAction(0, null);
  public void retryLicense() { invoke(retryLicense, null); }
  public void doRetryLicense() { license(); }
  
  private static BMuninnServiceContainer INSTANCE = null;
  private static BSystemPlatformService platServ;
  private static Ticket saveSchedule = null;
  
  public void started()
  {
    if (Sys.getStation() != null && Sys.getStation().isRunning())
    {
      platServ = (BSystemPlatformService) Sys.getService(BSystemPlatformService.TYPE);
      setVersionSchedule();
      setStationName(Sys.getStation().getStationName());
      setHostID(Sys.getHostId());
      setMuninnModuleVersion(Sys.loadModule("muninn").getVendorVersion().toString());
      
      license();
      
      if (getEnableSaveState() && getLicensed())
        startSaveSchedule();
    }
  }
  
  public void changed(Property p, Context cx)
  {
    if (!isRunning())
      return;
    
    if (Sys.getStation() != null && Sys.getStation().isRunning() && p.equals(licenseCode))
      license();
    
    if (Sys.getStation() != null && Sys.getStation().isRunning() && getLicensed())
    {
      if (p.equals(enableStationAutoSave) || p.equals(stationAutoSaveFrequency) || p.equals(stationAutoSaveVersionsToKeep))
        setVersionSchedule();
      
      if ((p.equals(enableSaveState) || p.equals(saveStateFrequency)) && getEnableSaveState())
        startSaveSchedule();
      
      if (p.equals(enableSaveState) && !getEnableSaveState())
        stopSaveSchedule();
    }
  }
  
  private void license()
  {
    setLicensed(Bob.testLic(this));
    if (!getLicensed())
    {
      BComponent[] children = this.getChildComponents();
      for (int i = 0; i < children.length; i++)
        this.remove(children[i].getName());
      
      Slot s = getSlot("licenseCode");
      setFlags(s, Flags.DEFAULT_ON_CLONE);
      setLicenseCode("");
    }
    
    else
    {
      Slot s = getSlot("licenseCode");
      setFlags(s, (getFlags(s) | Flags.READONLY));
    }
  }
  
  public void license(String name)
  {
    setLicensed(Bob.testLic(this));
    if (!getLicensed())
      this.remove(name);
  }
  
  private void setVersionSchedule()
  {
    platServ.setIsStationAutoSaveEnabled(getEnableStationAutoSave());
    platServ.setStationAutoSaveFrequency(getStationAutoSaveFrequency());
    if (getStationAutoSaveVersionsToKeep() > 3)
    {
      platServ.setStationSaveBackupCount(3);
      setStationAutoSaveVersionsToKeep(3);
    }
    else
      platServ.setStationSaveBackupCount(getStationAutoSaveVersionsToKeep());
  }
  
  private void startSaveSchedule()
  {
    stopSaveSchedule();
    saveSchedule = Clock.schedulePeriodically(this, getSaveStateFrequency(), saveStation, null);
  }
  
  private void stopSaveSchedule()
  {
    if (saveSchedule != null && !saveSchedule.isExpired())
      saveSchedule.cancel();
  }
  
  public final synchronized void serviceStarted() { INSTANCE = this; }
  
  public final synchronized void serviceStopped() { INSTANCE = null; }
  
  public static final BMuninnServiceContainer getInstance() { return INSTANCE; }
  
  public final boolean isParentLegal(BComponent comp) { return comp instanceof BServiceContainer; }
  
  public final boolean isChildLegal(BComponent comp) { return comp instanceof BMuninnService; }
  
  public static final Type TYPE = Sys.loadType(BMuninnServiceContainer.class);
  public Type[] getServiceTypes() { Type[] types = { TYPE }; return types; }
  public Type getType() { return TYPE; }
  
  public BIcon getIcon() { return icon; }
  private static final BIcon icon = BIcon.make("local:|module://muninn/org/muninn/niagara/graphics/MuninnGroup.PNG");
}
